package my.p2p.client;

import my.p2p.client.util.ThreadUtils;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;
import java.util.Scanner;

public class ClientToServer {

    static final Properties PROP;

    private Client client;
    private Socket socket;
    private BufferedReader inPunch;
    private BufferedWriter outPunch;
    private int localPort;

    static {
        PROP = new Properties();
        try {
            PROP.load(ClientToServer.class.getClassLoader().getResourceAsStream("config.properties"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private ClientToServer() {
        connectServer();
        ThreadUtils.execute(this::readForConsole);;
        ThreadUtils.execute(this::readForServer);
    }

    private synchronized void connectServer() {
        try {
            if (socket != null) {
                socket.close();
            }
            if (inPunch != null) {
                inPunch.close();
            }
            if (outPunch != null) {
                outPunch.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            socket = new Socket(PROP.getProperty("server.ip"), Integer.parseInt(PROP.getProperty("server.port")));
            localPort = socket.getLocalPort();
            inPunch = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            outPunch = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void readForConsole() {
        while (true) {
            try {
                Scanner scanner = new Scanner(System.in);
                String in = scanner.nextLine();
                if ("bye".equals(in)) {
                    client.closeClient();
                } else if (in.startsWith("file://")) {
                    client.writeToHole(in);
                } else if ("list".equals(in)) {
                    connectServer();
                    writeToServer(in);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void readForServer() {
        boolean flag = true;
        while (flag){
            try {
                String message = inPunch.readLine();
                System.out.println(message);
                if (!message.startsWith("ok::")) {
                    continue;
                }

                flag = false;
                String[] tokens = message.split("::");

                System.out.println("****************************************");
                System.out.println("远程地址: " + tokens[1] + ":" + tokens[2]);
                System.out.println("本地地址: " + tokens[3] + ":" + tokens[4]);
                System.out.println("本地端口：" + localPort);
                System.out.println("****************************************");
                socket.close();
                client = new Client();
                client.proceedHolePunching(tokens[1].trim(), Integer.parseInt(tokens[2]), localPort);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void writeToServer(String msg) throws IOException {
        outPunch.write(msg);
        outPunch.write('\n');
        outPunch.flush();
    }

    public static void main(String[] args) {
        new ClientToServer();
    }

}
